﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Runtime.Serialization

Namespace System.Workflow.ComponentModel.Serialization
    Friend NotInheritable Class ListSurrogate
        Implements ISerializationSurrogate
        ' Methods
        Friend Sub New()
        End Sub

        Private Sub System.Runtime.Serialization.ISerializationSurrogate.GetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializationSurrogate.GetObjectData
            If (Not obj.GetType.IsGenericType OrElse (Not obj.GetType.GetGenericTypeDefinition Is GetType(List([Of] )))) Then
                Throw New ArgumentException(SR.GetString("Error_InvalidArgumentValue"), "obj")
            End If
            Dim genericArguments As Type() = obj.GetType.GetGenericArguments
            If (genericArguments.Length <> 1) Then
                Throw New ArgumentException(SR.GetString("Error_InvalidArgumentValue"), "obj")
            End If
            Dim list As New ArrayList([TryCast](obj,IList))
            If (list.Count = 1) Then
                info.AddValue("item", list.Item(0))
            Else
                info.AddValue("items", list.ToArray)
            End If
            info.AddValue("itemType", genericArguments(0))
            info.SetType(GetType(ListRef))
        End Sub

        Private Function System.Runtime.Serialization.ISerializationSurrogate.SetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext, ByVal selector As ISurrogateSelector) As Object Implements ISerializationSurrogate.SetObjectData
            Return Nothing
        End Function


        ' Nested Types
        <Serializable> _
        Private NotInheritable Class ListRef
            Implements IObjectReference, IDeserializationCallback
            ' Methods
            Private Sub System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(ByVal sender As Object) Implements IDeserializationCallback.OnDeserialization
                If (Not Me.list Is Nothing) Then
                    Dim method As MethodInfo = Me.list.GetType.GetMethod("Add")
                    If (method Is Nothing) Then
                        Throw New NullReferenceException("addMethod")
                    End If
                    If (Not Me.items Is Nothing) Then
                        Dim i As Integer
                        For i = 0 To Me.items.Count - 1
                            method.Invoke(Me.list, New Object() { Me.items.Item(i) })
                        Next i
                    Else
                        method.Invoke(Me.list, New Object() { Me.item })
                    End If
                    Me.list = Nothing
                End If
            End Sub

            Private Function System.Runtime.Serialization.IObjectReference.GetRealObject(ByVal context As StreamingContext) As Object Implements IObjectReference.GetRealObject
                If (Me.list Is Nothing) Then
                    Dim type As Type = GetType(List([Of] Integer)).GetGenericTypeDefinition.MakeGenericType(New Type() { Me.itemType })
                    Me.list = type.GetConstructor(Type.EmptyTypes).Invoke(Nothing)
                End If
                Return Me.list
            End Function


            ' Fields
            <OptionalField> _
            Private item As Object
            <OptionalField> _
            Private items As IList
            Private itemType As Type
            <NonSerialized> _
            Private list As Object
        End Class
    End Class
End Namespace

